<template>
  <div class="card filter">
    <h4 v-if="title" class="title sle">
      {{ title }}
    </h4>
    <div class="search">
      <el-input v-model="filterText" placeholder="输入关键字进行过滤" clearable />
      <el-dropdown trigger="click">
        <el-icon size="20">
          <More />
        </el-icon>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item @click="toggleTreeNodes(true)">展开全部</el-dropdown-item>
            <el-dropdown-item @click="toggleTreeNodes(false)">折叠全部</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
    </div>
    <div class="operate-box">
      <slot name="operate"></slot>
    </div>
    <el-scrollbar :style="{ height: title ? `calc(100% - 95px)` : `calc(100% - 56px)` }">
      <el-tree ref="treeRef" default-expand-all :node-key="id" :data="multiple ? treeData : treeAllData"
        :show-checkbox="multiple" :check-strictly="false" :current-node-key="!multiple ? selected : ''"
        :highlight-current="!multiple" :expand-on-click-node="false" :check-on-click-node="multiple"
        :props="defaultProps" :filter-node-method="filterNode" :default-checked-keys="multiple ? selected : []"
        @node-click="handleNodeClick" @check="handleCheckChange">
        <template #default="scope">
          <span class="el-tree-node__label">
            <slot :row="scope">
              <div class="tree-filter-item">
                <div> {{ scope.node.label }}</div>
                <div>
                  <el-space :size="8">
                    <el-icon @click="event => { addOrEditChildNode(scope, '新增'); event.stopPropagation(); }">
                      <DocumentAdd />
                    </el-icon>
                    <el-icon @click="event => { addOrEditChildNode(scope, '编辑'); event.stopPropagation(); }">
                      <Edit />
                    </el-icon>
                    <el-icon @click="event => { deleteNode(scope); event.stopPropagation(); }">
                      <Delete />
                    </el-icon>
                  </el-space>
                </div>
              </div>
            </slot>
          </span>
        </template>
      </el-tree>
    </el-scrollbar>

    <OrganizeDialog ref="organizeDialogRef" :title="dialogTitle" :rowData="selectedRow"
      v-model:visible="dialogVisible" />
  </div>
</template>

<script setup lang="ts" name="TreeFilter">
import { ref, watch, onBeforeMount, nextTick } from "vue";
import { ElMessage, ElMessageBox, ElTree } from "element-plus";
import OrganizeDialog from "./OrganizeDialog.vue";
import { addOrganize, deleteOrganize, editOrganize, getOrganicTree, viewTheNumberOfPeople } from "@/api/modules/organize";

// 接收父组件参数并设置默认值
interface TreeFilterProps {
  requestApi?: (data?: any) => Promise<any>; // 请求分类数据的 api ==> 非必传
  data?: { [key: string]: any }[]; // 分类数据，如果有分类数据，则不会执行 api 请求 ==> 非必传
  title?: string; // treeFilter 标题 ==> 非必传
  id?: string; // 选择的id ==> 非必传，默认为 “id”
  label?: string; // 显示的label ==> 非必传，默认为 “label”
  multiple?: boolean; // 是否为多选 ==> 非必传，默认为 false
  defaultValue?: any; // 默认选中的值 ==> 非必传
}
const props = withDefaults(defineProps<TreeFilterProps>(), {
  id: "id",
  label: "label",
  multiple: false
});

const defaultProps = {
  children: "children",
  label: props.label
};

const treeRef = ref<InstanceType<typeof ElTree>>();
const treeData = ref<{ [key: string]: any }[]>([]);
const treeAllData = ref<{ [key: string]: any }[]>([]);

const selected = ref();
const setSelected = () => {
  if (props.multiple) selected.value = Array.isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue];
  else selected.value = typeof props.defaultValue === "string" ? props.defaultValue : "";
};

onBeforeMount(async () => {
  setSelected();
  if (props.requestApi) {
    const { data } = await props.requestApi!();
    treeData.value = data;
    treeAllData.value = [...data];
  }
});

const refreshTree = async () => {
  const res = await getOrganicTree();
  treeData.value = res;
  treeAllData.value = [...res];
};


// 使用 nextTick 防止打包后赋值不生效，开发环境是正常的
watch(
  () => props.defaultValue,
  () => nextTick(() => setSelected()),
  { deep: true, immediate: true }
);

watch(
  () => props.data,
  () => {
    if (props.data?.length) {
      treeData.value = props.data;
      treeAllData.value = [...props.data];
    }
  },
  { deep: true, immediate: true }
);

const filterText = ref("");
watch(filterText, val => {
  treeRef.value!.filter(val);
});

// 过滤
const filterNode = (value: string, data: { [key: string]: any }, node: any) => {
  if (!value) return true;
  let parentNode = node.parent,
    labels = [node.label],
    level = 1;
  while (level < node.level) {
    labels = [...labels, parentNode.label];
    parentNode = parentNode.parent;
    level++;
  }
  return labels.some(label => label.indexOf(value) !== -1);
};

// 切换树节点的展开或折叠状态
const toggleTreeNodes = (isExpand: boolean) => {
  let nodes = treeRef.value?.store.nodesMap;
  if (!nodes) return;
  for (const node in nodes) {
    if (nodes.hasOwnProperty(node)) {
      nodes[node].expanded = isExpand;
    }
  }
};

// emit
const emit = defineEmits<{
  change: [value: any];
}>();

// 单选
const handleNodeClick = (data: { [key: string]: any }) => {
  console.log(data);
  emit("change", data[props.id]);
};

// 多选
const handleCheckChange = () => {
  emit("change", treeRef.value?.getCheckedKeys());
};

//新增、编辑
const dialogTitle = ref('');
const dialogVisible = ref(false);
const selectedRow = ref<Partial<any>>({});
const organizeDialogRef = ref<InstanceType<typeof OrganizeDialog> | null>(null);

const addOrEditChildNode = (scope: any, title: string) => {
  dialogTitle.value = title;
  selectedRow.value = scope.data;
  dialogVisible.value = true;
  organizeDialogRef.value?.acceptParams({
    title,
    isView: title === '详情',
    row: scope.data,
    api: title === '新增' ? addOrganize : editOrganize,
    getTableList: refreshTree,
    allData: treeAllData.value,
  });
}

// 查看部门下面是否有人
const determineWhetherSomeone = async (deptId: any): Promise<boolean> => {
  return await viewTheNumberOfPeople(deptId);  // 返回一个布尔值
}

// 删除组织
const deleteNode = async (scope: any) => {
  const whetherToDelete = await determineWhetherSomeone(scope.data.id);

  if (whetherToDelete) {
    ElMessage({
      message: '请清空该组织内人员后再试！',
      type: 'warning',
      duration: 1500,
    });
    return;
  }

  ElMessageBox.confirm("确定删除该组织吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    const params = {
      ids: [scope.data[props.id]],
    };
    await deleteOrganize(params);
    ElMessage.success("删除组织成功");
    refreshTree();
  }).catch(() => {
    ElMessage.info("已取消删除");
  });
}

// 暴露给父组件使用
defineExpose({ treeData, treeAllData, treeRef });
</script>

<style scoped lang="scss">
@import "./index.scss";

.tree-filter-item {
  width: 150px;
  display: flex;
  justify-content: space-between;
  align-items: center;

  div:last-child {
    display: none; // 默认隐藏图标
  }

  &:hover {
    div:last-child {
      display: flex; // 鼠标移入时显示图标
    }
  }
}
</style>
